package com.example.demo.service.impl;

import com.coze.openapi.client.workflows.run.ResumeRunReq;
import com.coze.openapi.client.workflows.run.RunWorkflowReq;
import com.coze.openapi.client.workflows.run.RunWorkflowResp;
import com.coze.openapi.client.workflows.run.model.WorkflowEvent;
import com.coze.openapi.client.workflows.run.model.WorkflowEventType;
import com.coze.openapi.service.auth.TokenAuth;
import com.coze.openapi.service.service.CozeAPI;
import com.example.demo.service.WorkflowService;
import io.reactivex.Flowable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 工作流服务实现类
 * 提供工作流运行和流式工作流运行的具体实现
 */
@Service
public class WorkflowServiceImpl implements WorkflowService {

    private static final Logger logger = LoggerFactory.getLogger(WorkflowServiceImpl.class);

    @Value("${coze.workflow.url:https://api.coze.cn/v1/workflow/run}")
    private String workflowUrl;

    @Value("${coze.workflow.stream.url:https://api.coze.cn/v1/workflow/stream_run}")
    private String workflowStreamUrl;

    @Value("${coze.workflow.token}")
    private String workflowToken;

    private CozeAPI cozeAPI;
    private CozeAPI cozeStreamAPI;

    /**
     * 初始化Coze API客户端（普通工作流）
     */
    private void initCozeAPI() {
        if (cozeAPI == null) {
            if (!StringUtils.hasText(workflowToken)) {
                throw new RuntimeException("工作流token未配置");
            }

            TokenAuth authCli = new TokenAuth(workflowToken);

            // 通过access_token初始化Coze客户端
            cozeAPI = new CozeAPI.Builder()
                    .baseURL(workflowUrl)
                    .auth(authCli)
                    .readTimeout(10000)
                    .build();
        }
    }

    /**
     * 初始化Coze API客户端（流式工作流）
     */
    private void initCozeStreamAPI() {
        if (cozeStreamAPI == null) {
            if (!StringUtils.hasText(workflowToken)) {
                throw new RuntimeException("工作流token未配置");
            }

            TokenAuth authCli = new TokenAuth(workflowToken);

            // 通过access_token初始化Coze流式客户端
            cozeStreamAPI = new CozeAPI.Builder()
                    .baseURL(workflowStreamUrl)
                    .auth(authCli)
                    .readTimeout(30000) // 流式接口需要更长的超时时间
                    .build();
        }
    }

    @Override
    public String runWorkflow(String workflowID, Map<String, Object> parameters) {
        try {
            initCozeAPI();

            if (!StringUtils.hasText(workflowID)) {
                throw new IllegalArgumentException("工作流ID不能为空");
            }

            logger.info("开始运行工作流: {}, 参数: {}, API地址: {}", workflowID, parameters, workflowUrl);

            // 如果工作流需要输入参数，可以通过map发送
            Map<String, Object> data = parameters != null ? parameters : Map.of();

            RunWorkflowReq req = RunWorkflowReq.builder().workflowID(workflowID).parameters(data).build();

            RunWorkflowResp resp = cozeAPI.workflows().runs().create(req);

            logger.info("工作流运行完成: {}", resp);
            return resp.toString();

        } catch (Exception e) {
            logger.error("运行工作流时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("工作流运行失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String streamWorkflow(String workflowID, Map<String, Object> parameters) {
        try {
            initCozeStreamAPI();

            if (!StringUtils.hasText(workflowID)) {
                throw new IllegalArgumentException("工作流ID不能为空");
            }

            logger.info("开始流式运行工作流: {}, 参数: {}, API地址: {}", workflowID, parameters, workflowStreamUrl);

            // 如果工作流需要输入参数，可以通过map发送
            Map<String, Object> data = parameters != null ? parameters : Map.of();

            RunWorkflowReq req = RunWorkflowReq.builder().workflowID(workflowID).parameters(data).build();

            Flowable<WorkflowEvent> flowable = cozeStreamAPI.workflows().runs().stream(req);

            // 使用CompletableFuture来处理异步流式响应
            CompletableFuture<StringBuilder> future = new CompletableFuture<>();
            StringBuilder result = new StringBuilder();

            handleEvent(flowable, cozeStreamAPI, workflowID, result, future);

            // 等待结果，设置超时时间
            return future.get(30, TimeUnit.SECONDS).toString();

        } catch (Exception e) {
            logger.error("流式运行工作流时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("流式工作流运行失败: " + e.getMessage(), e);
        }
    }

    /**
     * 处理工作流事件
     * 流式接口将返回WorkflowEvent的迭代器。开发者应该遍历这个迭代器
     * 来获取WorkflowEvent并根据WorkflowEvent的类型分别处理它们。
     */
    private void handleEvent(Flowable<WorkflowEvent> events, CozeAPI coze, String workflowID, StringBuilder result, CompletableFuture<StringBuilder> future) {
        events.subscribe(event -> {
            try {
                if (event.getEvent().equals(WorkflowEventType.MESSAGE)) {
                    Object message = event.getMessage();
                    logger.info("收到消息: {}", message);
                    result.append("消息: ").append(message).append("\n");
                } else if (event.getEvent().equals(WorkflowEventType.ERROR)) {
                    Object error = event.getError();
                    logger.error("收到错误: {}", error);
                    result.append("错误: ").append(error).append("\n");
                } else if (event.getEvent().equals(WorkflowEventType.DONE)) {
                    Object message = event.getMessage();
                    logger.info("工作流完成: {}", message);
                    result.append("完成: ").append(message).append("\n");
                    future.complete(result);
                } else if (event.getEvent().equals(WorkflowEventType.INTERRUPT)) {
                    logger.info("收到中断事件，尝试恢复工作流");
                    handleEvent(coze.workflows().runs().resume(ResumeRunReq.builder().workflowID(workflowID).eventID(event.getInterrupt().getInterruptData().getEventID()).resumeData("your data").interruptType(event.getInterrupt().getInterruptData().getType()).build()), coze, workflowID, result, future);
                }
            } catch (Exception e) {
                logger.error("处理工作流事件时发生错误: {}", e.getMessage(), e);
                future.completeExceptionally(e);
            }
        }, throwable -> {
            logger.error("工作流事件流发生错误: {}", throwable.getMessage(), throwable);
            future.completeExceptionally(throwable);
        });

        // 关闭执行器
        coze.shutdownExecutor();
    }
}
